/*******************************************************************************
 * Copyright (c) 2002 Boris Pruessmann and others. All rights reserved. This
 * program and the accompanying materials are made available under the terms of
 * the Common Public License v0.5 which accompanies this distribution, and is
 * available at http://www.eclipse.org/legal/cpl-v05.html
 * 
 * Contributors: Boris Pruessmann - Initial implementation.
 ******************************************************************************/
package net.sourceforge.perforce.ui.dialogs;

import net.sourceforge.perforce.core.api.ResolveTypeEnum;
import net.sourceforge.perforce.ui.IPerforceUIConstants;
import net.sourceforge.perforce.ui.PerforceUIPlugin;
import net.sourceforge.perforce.ui.internal.Policy;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.swt.events.HelpEvent;
import org.eclipse.swt.events.HelpListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.help.WorkbenchHelp;

/**
 * @version $Revision: 488 $
 * @author <a href="mailto:bpruessmann@users.sourceforge.net">Boris
 *         Pruessmann</a>
 */
public class AutoResolveDialog extends Dialog {

  /** Combo: Resolve Type */
  private Combo resolveTypeCombo;

  /** Button: Re-resolve previously resolved but unsubmitted files */
  private Button reResolveButton;

  /** Button: Attempt textual merge of binary files */
  private Button attemptBinaryMergeButton;

  /** Indicates whether re-resolve is available or not. */
  private boolean enableReResolve;

  /** Stores the current selection. */
  private ResolveTypeEnum currentResolveType;

  /** Stores the current check state of the reResolveButton */
  private boolean currentReResolve;

  /** Stores the current check state of the attemptBinaryMergeButton */
  private boolean currentAttemptBinaryMerge;

  /**
   * Constructor for AutoResolveDialog.
   * 
   * @param parent the parent shell.
   * @param reResolveEnabled indicates whether the reResolveButton should be
   *        enabled or not.
   */
  public AutoResolveDialog(Shell parent, boolean reResolveEnabled) {
    super(parent);
    enableReResolve = reResolveEnabled;
  }

  /**
   * Called to retrieve the resolve type that was selectd.
   * 
   * @return THEIRS, YOURS, SAFE_AUTOMATIC, AUTOMATIC or AUTOMATIC_MARKERS.
   */
  public ResolveTypeEnum getResolveType() {
    return currentResolveType;
  }

  /**
   * Called to check whether the user wants to re-resolve previously resolved
   * files.
   * 
   * @return true or false.
   */
  public boolean shouldReResolve() {
    return enableReResolve ? currentReResolve : false;
  }

  /**
   * Indicates whether the user wants to perform a textual merge of binary
   * files.
   * 
   * @return true or false.
   */
  public boolean shouldAttemptBinaryMerge() {
    return currentAttemptBinaryMerge;
  }

  @Override
  public void create() {
    super.create();
    readSettings();
  }

  @Override
  public boolean close() {
    if (getReturnCode() == OK) {
      writeSettings();
    }

    return super.close();
  }

  @Override
  protected void configureShell(Shell newShell) {
    super.configureShell(newShell);
    newShell.setText(Policy.bind("AutoResolveDialog.title")); //$NON-NLS-1$
  }

  @Override
  protected Control createDialogArea(Composite parent) {
    Composite composite = DialogUtils.createComposite(parent, 2);

    DialogUtils.createLabel(composite, Policy.bind("AutoResolveDialog.ResolveType")); //$NON-NLS-1$

    resolveTypeCombo = DialogUtils.createCombo(composite, convertVerticalDLUsToPixels(140));
    fileResolveTypeCombo(resolveTypeCombo);

    resolveTypeCombo.setFocus();
    resolveTypeCombo.addHelpListener(new HelpListener() {
      public void helpRequested(HelpEvent event) {
        ResolveTypeEnum resolveType = ResolveTypeEnum.fromId(resolveTypeCombo.getSelectionIndex());
        if (resolveType == ResolveTypeEnum.ACCEPT_THEIRS) {
          WorkbenchHelp.displayHelp(IPerforceUIConstants.AUTO_RESOLVE_TYPE_THEIRS);
        } else if (resolveType == ResolveTypeEnum.ACCEPT_YOURS) {
          WorkbenchHelp.displayHelp(IPerforceUIConstants.AUTO_RESOLVE_TYPE_YOURS);
        } else if (resolveType == ResolveTypeEnum.SAFE_AUTOMATIC) {
          WorkbenchHelp.displayHelp(IPerforceUIConstants.AUTO_RESOLVE_TYPE_SAFE_AUTOMATIC);
        } else if (resolveType == ResolveTypeEnum.AUTOMATIC) {
          WorkbenchHelp.displayHelp(IPerforceUIConstants.AUTO_RESOLVE_TYPE_AUTOMATIC);
        } else if (resolveType == ResolveTypeEnum.AUTOMATIC_MARKERS) {
          WorkbenchHelp.displayHelp(IPerforceUIConstants.AUTO_RESOLVE_TYPE_AUTOMATIC_MARKERS);
        }
      }
    });
    resolveTypeCombo.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent event) {
        currentResolveType = ResolveTypeEnum.fromId(resolveTypeCombo.getSelectionIndex());
      }
    });

    // Re-Resolve button
    String buttonText = Policy.bind("AutoResolveDialog." + //$NON-NLS-1$
        "Re-resolve_previously_resolved_but_unsubmitted_files"); //$NON-NLS-1$
    reResolveButton = DialogUtils.createCheckButton(composite, buttonText);
    reResolveButton.setEnabled(enableReResolve);

    GridData data = new GridData();
    data.horizontalSpan = 2;
    reResolveButton.setLayoutData(data);

    reResolveButton.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent arg0) {
        currentReResolve = reResolveButton.getSelection();
      }
    });

    // Attempt binary merge button
    buttonText = Policy.bind("AutoResolveDialog.Attempt_textual_merge_of_binary_files"); //$NON-NLS-1$
    attemptBinaryMergeButton = DialogUtils.createCheckButton(composite, buttonText);

    data = new GridData();
    data.horizontalSpan = 2;
    attemptBinaryMergeButton.setLayoutData(data);

    attemptBinaryMergeButton.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent arg0) {
        currentAttemptBinaryMerge = attemptBinaryMergeButton.getSelection();
      }
    });

    return composite;
  }

  /**
   * Retrieves the associated IDialogSettings.
   * 
   * @return the dialog settings.
   */
  private IDialogSettings getDialogSettings() {
    IDialogSettings pluginSettings = PerforceUIPlugin.getPlugin().getDialogSettings();
    IDialogSettings dialogSettings = pluginSettings.getSection(getClass().getName());

    if (dialogSettings == null) {
      dialogSettings = pluginSettings.addNewSection(getClass().getName());
    }

    return dialogSettings;
  }

  /** Reads the dialogs settings. */
  private void readSettings() {
    IDialogSettings settings = getDialogSettings();

    try {
      currentResolveType = ResolveTypeEnum.fromId(settings.getInt("resolveType")); //$NON-NLS-1$
    } catch (NumberFormatException e) {
      currentResolveType = ResolveTypeEnum.ACCEPT_THEIRS;
    } finally {
      resolveTypeCombo.select(currentResolveType.getId());
    }

    currentReResolve = settings.getBoolean("reResolve"); //$NON-NLS-1$
    reResolveButton.setSelection(currentReResolve);

    currentAttemptBinaryMerge = settings.getBoolean("attemptBinaryMerge"); //$NON-NLS-1$
    attemptBinaryMergeButton.setSelection(currentAttemptBinaryMerge);
  }

  /** Writes the dialogs settings. */
  private void writeSettings() {
    IDialogSettings settings = getDialogSettings();

    settings.put("resolveType", currentResolveType.getId()); //$NON-NLS-1$
    settings.put("reResolve", currentReResolve); //$NON-NLS-1$
    settings.put("attemptBinaryMerge", currentAttemptBinaryMerge); //$NON-NLS-1$
  }

  /**
   * Fills the given combo with the available resolve types.
   * 
   * @param combo the combo to fill.
   */
  private static void fileResolveTypeCombo(Combo combo) {
    combo.add(Policy.bind("AutoResolveDialog.Accept_theirs")); //$NON-NLS-1$
    combo.add(Policy.bind("AutoResolveDialog.Accept_yours")); //$NON-NLS-1$
    combo.add(Policy.bind("AutoResolveDialog.Safe_automatic_resolve")); //$NON-NLS-1$
    combo.add(Policy.bind("AutoResolveDialog.Automatic_resolve")); //$NON-NLS-1$
    combo.add(Policy.bind("AutoResolveDialog.Automatic_resolve,_including_conflict_markers_9")); //$NON-NLS-1$
  }
}
